using System;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class MissionPlayer : MonoBehaviour, IPlayer
{
	[Serializable]
	public class PlayerData : IPlayerData
	{
		public int ShotCount;

		public int PottedCount;

		public float HitRate;

		public int Combo;

		public int MaxCombo;

		public int ShotsRemain = 5;

		public int HighScore;

		public int Score;

		public int Star;

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("FireCount : ").Append(ShotCount).Append('\n')
				.Append("Potted count : ")
				.Append(PottedCount)
				.Append('\n')
				.Append("Hit rate : ")
				.Append(HitRate)
				.Append('\n')
				.Append("Link : ")
				.Append(Combo)
				.Append('\n')
				.Append("Max link : ")
				.Append(MaxCombo)
				.Append('\n')
				.Append("Shot remain : ")
				.Append(ShotsRemain)
				.Append('\n')
				.Append("Hight score : ")
				.Append(HighScore)
				.Append('\n')
				.Append("Score : ")
				.Append(Score)
				.Append('\n')
				.Append("Star : ")
				.Append(Star);
			return stringBuilder.ToString();
		}
	}

	private enum UpOrDown
	{
		Up = 1,
		Down = -1
	}

	private enum TableBorder
	{
		None,
		TopLeft,
		TopRight,
		Right,
		BottomRight,
		BottomLeft,
		Left
	}

	[SerializeField]
	private Text m_ShotsRemain;

	[SerializeField]
	private Text m_LevelName;

	[SerializeField]
	private Text m_Score;

	private bool m_MarkPotted;

	protected PlayerData m_PlayerData = new PlayerData();

	private bool _startDraw;

	public int playerID
	{
		get;
		set;
	}

	public PlayerData Data => m_PlayerData;

	public int ShotsRemain
	{
		get
		{
			return m_PlayerData.ShotsRemain;
		}
		set
		{
			m_PlayerData.ShotsRemain = ((value >= 0) ? value : 0);
			m_ShotsRemain.text = m_PlayerData.ShotsRemain.ToString();
		}
	}

	public int FireCount
	{
		get
		{
			return m_PlayerData.ShotCount;
		}
		set
		{
			m_PlayerData.ShotCount = value;
		}
	}

	public float HitRate
	{
		get
		{
			return m_PlayerData.HitRate;
		}
		set
		{
			m_PlayerData.HitRate = value;
		}
	}

	public int Combo
	{
		get
		{
			return m_PlayerData.Combo;
		}
		set
		{
			m_PlayerData.Combo = value;
			if (m_PlayerData.MaxCombo < m_PlayerData.Combo)
			{
				m_PlayerData.MaxCombo = m_PlayerData.Combo;
			}
			GameStatistics.MarkMaxCombo(m_PlayerData.Combo);
		}
	}

	public int Score
	{
		get
		{
			return m_PlayerData.Score;
		}
		set
		{
			if (value <= 0)
			{
				m_PlayerData.Score = 0;
			}
			else
			{
				m_PlayerData.Score = value;
			}
			if (m_PlayerData.HighScore < m_PlayerData.Score)
			{
				m_PlayerData.HighScore = m_PlayerData.Score;
			}
			m_Score.text = Score.ToString();
		}
	}

	public void Pot()
	{
		if (!m_MarkPotted)
		{
			m_PlayerData.PottedCount++;
			m_MarkPotted = true;
		}
	}

	public void AddCues(int cue, Vector3 position)
	{
		if (cue != 0)
		{
			ShotsRemain += cue;
			string text = string.Format(HOLocalizationConfiguration.GetValue(113), cue);
			Color c = (cue <= 0) ? Color.red : Color.yellow;
			BaseUIController.GenerateTips(text, c, position);
		}
	}

	public void AddCues(int cue, PocketTrigger pocket)
	{
		if (cue != 0)
		{
			AddCues(cue, MathTools.World2UI(pocket.GetRealPosition()));
		}
	}

	public void AddScore(int score, PocketTrigger pocket)
	{
		int num = (int)((float)(score * (m_PlayerData.Combo + 4)) * 0.2f);
		Score += num;
		if ((bool)pocket)
		{
			string text = (Combo <= 1) ? ("+" + num) : ("组合 " + Combo + "\n+" + num);
			BaseUIController.GenerateTips(text, Color.yellow, MathTools.World2UI(pocket.GetRealPosition()));
		}
	}

	private void Awake()
	{
		PoolRulesBase.onGameOver = (Delegate1Args<IPlayer>)Delegate.Combine(PoolRulesBase.onGameOver, new Delegate1Args<IPlayer>(GameOver));
		BombBall.GameoverWithBoom = (Delegate1Args<IPlayer>)Delegate.Combine(BombBall.GameoverWithBoom, new Delegate1Args<IPlayer>(GameOver));
		DemonBall.GameOverWithPotted = (Delegate1Args<IPlayer>)Delegate.Combine(DemonBall.GameOverWithPotted, new Delegate1Args<IPlayer>(GameOver));
		PoolRulesBase.onNewTurn = (Delegate1Args<int>)Delegate.Combine(PoolRulesBase.onNewTurn, new Delegate1Args<int>(TurnBegin));
		PoolRulesBase.onFireBall = (Delegate0Args)Delegate.Combine(PoolRulesBase.onFireBall, new Delegate0Args(FireBall));
		m_LevelName.text = LevelDataIndex.CurrentLevel.FileName;
		m_ShotsRemain.text = m_PlayerData.ShotsRemain.ToString();
		m_Score.text = "0";
	}

	private void OnDestroy()
	{
		PoolRulesBase.onGameOver = (Delegate1Args<IPlayer>)Delegate.Remove(PoolRulesBase.onGameOver, new Delegate1Args<IPlayer>(GameOver));
		BombBall.GameoverWithBoom = (Delegate1Args<IPlayer>)Delegate.Remove(BombBall.GameoverWithBoom, new Delegate1Args<IPlayer>(GameOver));
		DemonBall.GameOverWithPotted = (Delegate1Args<IPlayer>)Delegate.Remove(DemonBall.GameOverWithPotted, new Delegate1Args<IPlayer>(GameOver));
		PoolRulesBase.onNewTurn = (Delegate1Args<int>)Delegate.Remove(PoolRulesBase.onNewTurn, new Delegate1Args<int>(TurnBegin));
		PoolRulesBase.onFireBall = (Delegate0Args)Delegate.Remove(PoolRulesBase.onFireBall, new Delegate0Args(FireBall));
	}

	protected void TurnBegin(int turn)
	{
		m_MarkPotted = false;
	}

	private void OnRateThisAppDestroy()
	{
		BaseUIController.MSettlement.MissionComplete(m_PlayerData);
	}

	private bool OpenRateAppDialog()
	{
		/* if (!PlayerPrefs.HasKey("StarRateKey"))
		{
			int index = ConstantData.LevelDatas.GetIndex(LevelDataIndex.CurrentLevel.FileName);
			if (index == 4)
			{
				UIADViewWnd.Show(UIADViewWnd.ADViewType.Rate);
				return true;
			}
		} */
		return false;
	}

	protected void GameOver(IPlayer player)
	{
		string fileName = LevelDataIndex.CurrentLevel.FileName;
		m_PlayerData.HitRate = ((m_PlayerData.ShotCount != 0) ? ((float)m_PlayerData.PottedCount / (float)m_PlayerData.ShotCount) : 0f);
		int num = 0;
		if (player != null && player.playerID == playerID)
		{
			AddScore(ShotsRemain * 200, null);
			m_PlayerData.Star = LayoutConfiguration.instance[fileName].GetStarWithScore(m_PlayerData.Score);
			int star = ConstantData.missionRecords.GetStar(fileName);
			GameStatistics.MarkMissionStars(Mathf.Max(0, m_PlayerData.Star - star));
			num = Mathf.Max(star, m_PlayerData.Star);
			ConstantData.missionRecords.Record(fileName, num, m_PlayerData.HighScore);
			//StreamTools.SerializeObject(ConstantData.missionRecords, ConstantData.missionLevelDataRecordPath);
			string json = ConstantData.missionRecords.ToJson();
			PlayerPrefs.SetString("MissionRecords", json);
			PlayerPrefs.Save();
			if (OpenRateAppDialog())
			{
				UIADViewWnd.OnRateThisAppDestroy = OnRateThisAppDestroy;
			}
			else
			{
				BaseUIController.MSettlement.MissionComplete(m_PlayerData);
			}
			if (GameManager.Rules.firstRound)
			{
				ConstantData.achieveRecords.Mark(fileName, AchieveType.Finish | AchieveType.FinishWithTriangularPole);
			}
			else
			{
				ConstantData.achieveRecords.Mark(fileName, AchieveType.Finish);
			}
		}
		else
		{
			if (string.IsNullOrEmpty(ConstantData.prevLevelName))
			{
				ConstantData.prevLevelName = LevelDataIndex.CurrentLevel.FileName;
				ConstantData.missionFailedCount = 1;
			}
			else if (ConstantData.prevLevelName.CompareTo(LevelDataIndex.CurrentLevel.FileName) == 0)
			{
				ConstantData.missionFailedCount++;
			}
			else
			{
				ConstantData.prevLevelName = LevelDataIndex.CurrentLevel.FileName;
				ConstantData.missionFailedCount = 1;
			}
			if (ConstantData.vedioMissionCount > 0 && !ConstantData.watchedAdAtThisBattle && AdManagerOld.instance.curAd.HasVideo())
			{
				TextDialog.Show2Button("Watch video and install the app to \nGet extra <color=#ff0000><size=75>+2 cues</size></color>", OnDialogSure, OnDialogCancel, bShowIcon: true);
				ConstantData.vedioMissionCount--;
			}
			else
			{
				Advertising.PopIngameAd();
				BaseUIController.MSettlement.MissionFail(m_PlayerData);
			}
		}
	}

	protected void OnDialogSure()
	{
		AdManagerOld.instance.PlayVideo(0, delegate
		{
			ConstantData.vedioMissionCount += 2;
		});
		ConstantData.missionFailedCount = 0;
		ConstantData.watchedAdAtThisBattle = true;
	}

	protected void OnDialogCancel()
	{
		BaseUIController.MSettlement.MissionFail(m_PlayerData);
	}

	protected void FireBall()
	{
		m_PlayerData.ShotCount++;
		AddCues(-1, m_ShotsRemain.transform.position);
	}

	public void Continue()
	{
		AddCues(2, m_ShotsRemain.transform.position);
	}

	public void GetReboundHitBall(out PoolBall targetBall, out Vector3 hitPoint)
	{
		targetBall = null;
		hitPoint = Vector3.zero;
		for (int i = 0; i < Pools.CustomBallsArray.Length; i++)
		{
			PoolBall poolBall = Pools.CustomBallsArray[i];
			if (poolBall.BallState != PoolBall.State.IDLE)
			{
				continue;
			}
			PocketTrigger closestPocket = GetClosestPocket(poolBall);
			if (closestPocket != null)
			{
				if (closestPocket.PocketIndex == PocketIndexes.TopCenter)
				{
					hitPoint = GetRayReboundHitPoint(poolBall, UpOrDown.Up);
				}
				else if (closestPocket.PocketIndex == PocketIndexes.BottomCenter)
				{
					hitPoint = GetRayReboundHitPoint(poolBall, UpOrDown.Down);
				}
				if (hitPoint != Vector3.zero)
				{
					targetBall = poolBall;
				}
			}
		}
	}

	private PocketTrigger GetPocketTrigger(UpOrDown dir)
	{
		PocketIndexes pocketIndexes = PocketIndexes.None;
		switch (dir)
		{
			case UpOrDown.Up:
				pocketIndexes = PocketIndexes.BottomCenter;
				break;
			case UpOrDown.Down:
				pocketIndexes = PocketIndexes.TopCenter;
				break;
		}
		for (int i = 0; i < Pools.PocketTriggers.Count; i++)
		{
			PocketTrigger pocketTrigger = Pools.PocketTriggers[i];
			if (pocketTrigger.PocketIndex == pocketIndexes)
			{
				return pocketTrigger;
			}
		}
		return null;
	}

	private Vector3 GetRayReboundHitPoint(PoolBall ball, UpOrDown dir)
	{
		Ray ray = new Ray(ball.position, new Vector3(0f, 0f, 1f * (float)dir));
		UnityEngine.Debug.DrawRay(ray.origin, ray.direction, Color.yellow);
		if (Physics.SphereCast(ray, ball.GetRadius(), out RaycastHit hitInfo))
		{
			UnityEngine.Debug.Log("hit:" + hitInfo.transform.name);
			Vector3 point = hitInfo.point;
			float z = point.z;
			Vector3 position = ball.position;
			float num = Mathf.Abs(z - position.z);
			Vector3 a = point + new Vector3(0f, 0f, num * (float)dir);
			Vector3 realPosition = GetPocketTrigger(dir).GetRealPosition();
			Ray ray2 = new Ray(realPosition, a - realPosition);
			UnityEngine.Debug.DrawRay(ray2.origin, ray2.direction);
			if (Physics.Raycast(ray2, out RaycastHit hitInfo2))
			{
				string name = hitInfo2.transform.name;
				UnityEngine.Debug.Log("rebound hit:" + name);
				if (name.Contains("Rail_"))
				{
					string value = name.Substring(5);
					if (value.ToEnum(TableBorder.None) != 0)
					{
						return hitInfo2.point;
					}
				}
			}
		}
		return Vector3.zero;
	}

	private PocketTrigger GetClosestPocket(PoolBall ball)
	{
		PocketTrigger result = null;
		float num = 10000f;
		Vector3 zero = Vector3.zero;
		Vector3 zero2 = Vector3.zero;
		for (int i = 0; i < Pools.PocketTriggers.Count; i++)
		{
			PocketTrigger pocketTrigger = Pools.PocketTriggers[i];
			float num2 = Vector3.Distance(ball.position, pocketTrigger.GetRealPosition());
			if (pocketTrigger.PocketIndex == PocketIndexes.TopRight)
			{
				zero = pocketTrigger.GetRealPosition();
			}
			else if (pocketTrigger.PocketIndex == PocketIndexes.BottomLeft)
			{
				zero2 = pocketTrigger.GetRealPosition();
			}
			if (num2 < num)
			{
				result = pocketTrigger;
				num = num2;
			}
		}
		return result;
	}

	public Vector3 GetReboundHitPoint()
	{
		Vector3 inNormal = default(Vector3);
		for (int i = 0; i < Pools.CustomBallsArray.Length; i++)
		{
			PoolBall poolBall = Pools.CustomBallsArray[i];
			if (poolBall.BallState != PoolBall.State.IDLE)
			{
				continue;
			}
			PocketTrigger closestPocket = GetClosestPocket(poolBall);
			if (!(closestPocket != null))
			{
				continue;
			}
			Ray ray = new Ray(closestPocket.GetRealPosition(), poolBall.position - closestPocket.GetRealPosition());
			RaycastHit[] array = Physics.RaycastAll(ray);
			UnityEngine.Debug.DrawRay(ray.origin, ray.direction, Color.yellow);
			if (array.Length != 2)
			{
				continue;
			}
			for (int j = 0; j < array.Length; j++)
			{
				string name = array[j].transform.name;
				if (!name.Contains("Rail_"))
				{
					continue;
				}
				string value = name.Substring(5);
				if (value.ToEnum(TableBorder.None) != 0)
				{
					Vector3 normal = array[j].normal;
					float x = normal.x;
					Vector3 normal2 = array[j].normal;
					inNormal = new Vector3(x, 0f, normal2.z);
					Vector3 vector = Vector3.Reflect(ray.direction, inNormal);
					Vector3 point = array[j].point;
					Vector3 point2 = array[j].point;
					UnityEngine.Debug.DrawLine(point, new Vector3(0f, point2.y, 0f), Color.red);
					Ray ray2 = new Ray(array[j].point, vector);
					UnityEngine.Debug.DrawRay(array[j].point, vector, Color.black);
					if (Physics.Raycast(ray2, 100f, LayerMask.GetMask("WhiteBall")))
					{
						UnityEngine.Debug.Log("reflect cast hit white ball");
						return array[j].point;
					}
				}
			}
		}
		return Vector3.zero;
	}

	private void Update()
	{
		if (UnityEngine.Input.GetKeyDown(KeyCode.T))
		{
			UnityEngine.Debug.Log("press T!");
			_startDraw = !_startDraw;
		}
		if (_startDraw)
		{
			GetReboundHitBall(out PoolBall _, out Vector3 _);
		}
	}
}
